package controller

import (
	"GoTime/models"
	"net/http"
	"sort"
	"time"

	"github.com/gin-gonic/gin"
	"xorm.io/xorm"
)

type Menu struct {
	ID       int    `json:"id"`
	Name     string `json:"name"`
	ParentID int    `json:"parent_id"`
	Sort     int    `json:"sort"`
	// 其他字段...
	SubMenus []*Menu `json:"sub_menus,omitempty"`
}

func GetMenuList(c *gin.Context) {
	// 获取菜单列表并处理结果
	list, err := new(models.Menu).GetMenuList()
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error(), "data": nil})
		return
	}

	// 对菜单列表进行排序
	SortMenuList(list)

	// 构建菜单树
	BuildMenuTree(list)

	// 将顶级菜单（ParentID 为 0 的菜单项）添加到一个切片中
	var treeSlice []*models.MenuList
	for _, menu := range list {
		if menu.ParentId == 0 { // 假设顶级菜单的 ParentID 是 0
			treeSlice = append(treeSlice, menu)
		}
	}

	// 对每个顶级菜单的子菜单进行排序
	for _, menu := range treeSlice {
		sort.Slice(menu.SubMenus, func(i, j int) bool {
			return menu.SubMenus[i].Sort < menu.SubMenus[j].Sort
		})
	}

	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "获取成功", "data": treeSlice})
	return
}
func BuildMenuTree(menus []*models.MenuList) map[int]*models.MenuList {
	menuMap := make(map[int]*models.MenuList)

	// 将所有菜单项放入 map 中
	for _, menu := range menus {
		menuMap[menu.Id] = menu
	}

	// 构建子菜单
	var menuTree []*models.MenuList
	for _, menu := range menus {
		if parent, exists := menuMap[menu.ParentId]; exists {
			parent.SubMenus = append(parent.SubMenus, menu)
		} else {
			menuTree = append(menuTree, menu)
		}
	}

	return menuMap
}

// SortMenuList 根据 Sort 字段对菜单列表进行排序
func SortMenuList(menus []*models.MenuList) {
	sort.Slice(menus, func(i, j int) bool {
		return menus[i].Sort < menus[j].Sort
	})
}

// AddMenu 新增菜单
func AddMenu(c *gin.Context) {
	// 声明一个 Menu 类型的变量用于接收请求中的数据
	var menu models.Menu

	// 使用 BindJSON 方法将请求 body 中的 JSON 数据绑定到 menu 变量
	if err := c.ShouldBindJSON(&menu); err != nil {
		// 如果绑定失败，返回错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}
	var engine *xorm.Engine
	engine = models.Engine
	session := engine.NewSession()
	defer session.Close() // 确保在函数结束时关闭会话，释放资源

	// 开始一个新的事务，在执行任何数据库操作之前调用 Begin()
	err := session.Begin()
	if err != nil {
		// 如果开始事务出错，回滚事务以确保数据一致性
		session.Rollback()
		// 返回错误信息给客户端
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}

	// 设置菜单的创建时间为当前时间
	menu.CreatedAt = time.Now()
	// 设置菜单的更新时间为当前时间
	menu.UpdatedAt = time.Now()
	// 向数据库中插入新的菜单记录
	_, err = session.Insert(menu)
	if err != nil {
		// 如果插入操作出错，回滚事务
		session.Rollback()
		// 返回错误信息给客户端
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}

	// 提交事务，确保所有操作都被成功记录
	err = session.Commit()
	if err != nil {
		// 如果提交事务出错，回滚事务
		session.Rollback()
		// 返回错误信息给客户端
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}

	// 菜单添加成功，返回成功信息
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "菜单添加成功"})
	return
}

func MenuEdit(c *gin.Context) {
	// 声明一个 Menu 类型的变量用于接收请求中的数据
	var menu models.Menu

	// 使用 BindJSON 方法将请求 body 中的 JSON 数据绑定到 menu 变量
	if err := c.ShouldBindJSON(&menu); err != nil {
		// 如果绑定失败，返回错误信息
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}
	var engine *xorm.Engine        // 声明一个 xorm.Engine 类型的变量
	engine = models.Engine         // 赋值给 engine
	session := engine.NewSession() // 创建一个新的会话
	defer session.Close()          // 确保在函数结束时关闭会话，释放资源

	// 开始一个新的事务，在执行任何数据库操作之前调用 Begin()
	err := session.Begin()
	if err != nil {
		// 如果开始事务出错，回滚事务以确保数据一致性
		session.Rollback()
		// 返回错误信息给客户端
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}

	// 设置菜单的更新时间为当前时间
	menu.UpdatedAt = time.Now()
	// 更新数据库中菜单记录
	_, err = session.ID(menu.Id).Update(menu)
	if err != nil {
		// 如果更新操作出错，回滚事务
		session.Rollback()
		// 返回错误信息给客户端
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}

	// 提交事务，确保所有操作都被成功记录
	err = session.Commit()
	if err != nil {
		// 如果提交事务出错，回滚事务
		session.Rollback()
		// 返回错误信息给客户端
		c.JSON(http.StatusOK, gin.H{"code": 201, "msg": err.Error()})
		return
	}

	// 菜单更新成功，返回成功信息
	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "菜单更新成功"})
	return
}

type Request struct {
	ID int `json:"id"`
}

func MenuDelete(c *gin.Context) {
	// 声明一个 Request 类型的变量
	var req Request
	// 使用 ShouldBindJSON 绑定 JSON 数据到 req 变量
	if err := c.ShouldBindJSON(&req); err != nil {
		// 如果绑定失败，返回错误信息
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 获取要删除的菜单 ID
	menuId := req.ID

	var engine *xorm.Engine        // 声明一个 xorm.Engine 类型的变量
	engine = models.Engine         // 赋值给 engine
	session := engine.NewSession() // 创建一个新的会话
	defer session.Close()          // 确保在函数结束时关闭会话，释放资源

	// 开始一个新的事务，在执行任何数据库操作之前调用 Begin()
	err := session.Begin()
	if err != nil {
		// 如果开始事务出错，回滚事务以确保数据一致性
		session.Rollback()
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 删除数据库中菜单记录
	_, err = session.ID(menuId).Delete(new(models.Menu))
	if err != nil {
		// 如果删除操作出错，回滚事务
		session.Rollback()
		// 返回错误信息给客户端
		c.JSON(http.StatusOK, gin.H{"error": err.Error()})
		return
	}

	// 提交事务，确保所有操作都被成功记录
	err = session.Commit()
	if err != nil { // 如果提交事务出错，回滚事务
		session.Rollback()
		// 返回错误信息给客户端
		c.JSON(http.StatusOK, gin.H{"error": err.Error()})
		return
	}

	// 菜单删除成功，返回成功信息
	c.JSON(http.StatusOK, gin.H{"message": "菜单删除成功"})
}
